package com.triones.api.service.interlace.impl;

import cn.hutool.core.convert.Convert;
import cn.hutool.json.JSONUtil;
import com.amazonaws.util.json.Jackson;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.common.enums.PushNotificationEnum;
import com.ruoyi.common.utils.CardMgtFeeUtil;
import com.ruoyi.common.utils.DateUtil;
import com.ruoyi.common.utils.SnCreator;
import com.triones.api.entity.CardMgrFeeDO;
import com.triones.api.entity.FeeThaliDO;
import com.triones.api.entity.interlace.bo.HandleInternalTransferCryptoBO;
import com.triones.api.entity.interlace.bo.request.CreateInfinityCardToBudgetRequest;
import com.triones.api.entity.interlace.bo.request.ListAllBalancesRequest;
import com.triones.api.entity.interlace.dto.*;
import com.triones.api.entity.vo.FeeThaliVO;
import com.triones.api.mapper.CardMgrFeeMapper;
import com.triones.api.mapper.FeeThaliMapper;
import com.triones.api.mapper.interlace.*;
import com.triones.api.service.interlace.*;
import com.triones.api.service.third.InterlaceService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import static com.ruoyi.common.utils.DateUtil.timestampToDateStrToyyyyMMdd;

/**
 * interlace 回调异步处理
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class AsyncWebhookServiceImpl implements AsyncWebhookService {

    private final InterlaceCommunalService interlaceCommunalService;

    private final InterlaceService interlaceService;

    private final InterlaceCryptoService interlaceCryptoService;

    private final InterlaceFiatService interlaceFiatService;

    private final InterlaceMemberMapper interlaceMemberMapper;

    private final InterlaceBalancesMapper interlaceBalancesMapper;

    private final InterlaceQuantumTransferMapper interlaceQuantumTransferMapper;

    private final InterlaceKycMapper interlaceKycMapper;

    private final InterlaceCryptoWalletMapper interlaceCryptoWalletMapper;

    private final InterlaceTransfersMapper interlaceTransfersMapper;

    private final InterlaceCardHolderMapper interlaceCardHolderMapper;

    private final InterlaceBudgetTransactionMapper interlaceBudgetTransactionMapper;

    private final InterlaceInfinityCardMapper interlaceInfinityCardMapper;

    private final InterlaceCardTransactionMapper interlaceCardTransactionMapper;

    private final InterlaceCardApplyMapper interlaceCardApplyMapper;

    private final CardMgrFeeMapper cardMgrFeeMapper;

    private final FeeThaliMapper feeThaliMapper;

    private final InterlaceCardTransactionFeeMapper interlaceCardTransactionFeeMapper;

    private final InterlaceQuantumTransferFeesMapper interlaceQuantumTransferFeesMapper;

    private final PushService pushService;

    private final InterlaceCardBillStatisticsService interlaceCardBillStatisticsService;

    @Override
    public void accountRegistered(Map data) {
        if (data != null) {
            InterlaceMemberDO interlaceMemberDO = interlaceMemberMapper.selectOne(new LambdaQueryWrapper<InterlaceMemberDO>()
                .eq(InterlaceMemberDO::getInterlaceAccountId, Convert.toStr(data.get("id"))));
            if (interlaceMemberDO != null) {
                interlaceMemberDO.setInterlaceAccountStatus(Convert.toStr(data.get("status")));
                interlaceMemberMapper.updateById(interlaceMemberDO);
            }
        }
    }

    @Async
    @Override
    public void kyc(Map data) {
        if (data != null) {
            String kycStatus = Convert.toStr(data.get("kycStatus"));
            String accountId = Convert.toStr(data.get("id"));
            InterlaceKycDO interlaceKycDO = interlaceKycMapper.selectOne(new LambdaQueryWrapper<InterlaceKycDO>()
                .eq(InterlaceKycDO::getInterlaceAccountId, accountId)
                .ne(InterlaceKycDO::getStatus, "Passed"));
            if (interlaceKycDO != null) {
                InterlaceMemberDO interlaceMemberDO = interlaceMemberMapper.selectOne(new LambdaQueryWrapper<InterlaceMemberDO>()
                    .eq(InterlaceMemberDO::getInterlaceAccountId, accountId));
                if (interlaceMemberDO != null) {
                    interlaceMemberDO.setInterlaceAccountKycStatus(kycStatus);
                    interlaceMemberMapper.updateById(interlaceMemberDO);
                }
                interlaceKycDO.setStatus(kycStatus);
                interlaceKycDO.setFailRemark(Convert.toStr(data.get("message")));
                interlaceKycDO.setUpdateTime(System.currentTimeMillis());
                interlaceKycMapper.updateById(interlaceKycDO);

                /** 发起初始化账户 */
                if ("Passed".equals(kycStatus)) {
                    interlaceCryptoService.initialization(accountId);

                    /** 推送-KYC审核结果通知 */
                    String pushType = "kyc_audit";
                    PushNotificationEnum notification = PushNotificationEnum.fromPushType(pushType);
                    String zhContent = notification.getZhContent();
                    String enContent = notification.getEnContent();
                    String jaContent = notification.getJaContent();
                    pushService.push(pushType, zhContent, enContent, jaContent, interlaceKycDO.getUid());
                }
            }
        }
    }

    @Async
    @Override
    public void cryptoConnectWallet(Map data) {
        if (data != null) {
            String accountId = Convert.toStr(data.get("accountId"));
            String walletId = Convert.toStr(data.get("id"));
            InterlaceCryptoWalletDO interlaceWalletDO = interlaceCryptoWalletMapper.selectOne(new LambdaQueryWrapper<InterlaceCryptoWalletDO>()
                .eq(InterlaceCryptoWalletDO::getInterlaceAccountId, accountId)
                .eq(InterlaceCryptoWalletDO::getWalletId, walletId));
            if (interlaceWalletDO == null) {
                InterlaceMemberDO interlaceMemberDO = interlaceMemberMapper.selectOne(new LambdaQueryWrapper<InterlaceMemberDO>()
                    .eq(InterlaceMemberDO::getInterlaceAccountId, accountId));
                interlaceWalletDO = new InterlaceCryptoWalletDO();
                Long uid = null;
                if (interlaceMemberDO != null) {
                    uid = interlaceMemberDO.getId();
                    /** 创建持卡人待申请记录 */
                    interlaceFiatService.createCardHolder(accountId, uid);
                    /** 创建预算组待申请记录 */
                    interlaceFiatService.createBudget(accountId, uid);
                }
                interlaceWalletDO.setUid(uid);
                interlaceWalletDO.setWalletId(walletId);
                interlaceWalletDO.setInterlaceAccountId(accountId);
                interlaceWalletDO.setNickname(Convert.toStr(data.get("nickname")));
                interlaceWalletDO.setMaster(Convert.toBool(data.get("master")) ? 1 : 0);
                interlaceWalletDO.setCurrency(Convert.toStr(data.get("currency")));
                interlaceWalletDO.setCreateTime(System.currentTimeMillis());
                interlaceCryptoWalletMapper.insert(interlaceWalletDO);
                /** 获取一个币种钱包 */
                Map wallet = interlaceCryptoService.getWallet(walletId);
                if (wallet != null) {
                    List<Map> balances = (List<Map>) wallet.get("balances");
                    if (balances != null && balances.size() > 0) {
                        for (Map balance : balances) {
                            String balanceId = Convert.toStr(balance.get("id"));
                            InterlaceBalancesDO interlaceWalletBalancesDO = interlaceBalancesMapper.selectOne(new LambdaQueryWrapper<InterlaceBalancesDO>()
                                .eq(InterlaceBalancesDO::getBid, balanceId)
                                .last("FOR UPDATE"));
                            if (interlaceWalletBalancesDO == null) {
                                interlaceWalletBalancesDO = new InterlaceBalancesDO();
                                interlaceWalletBalancesDO.setUid(uid);
                                interlaceWalletBalancesDO.setInterlaceAccountId(accountId);
                                interlaceWalletBalancesDO.setWalletId(walletId);
                                interlaceWalletBalancesDO.setBid(balanceId);
                                interlaceWalletBalancesDO.setCurrency(Convert.toStr(balance.get("currency")));
                                interlaceWalletBalancesDO.setAvailable(Convert.toBigDecimal(balance.get("available"), BigDecimal.ZERO));
                                interlaceWalletBalancesDO.setPending(Convert.toBigDecimal(balance.get("pending"), BigDecimal.ZERO));
                                interlaceWalletBalancesDO.setFrozen(Convert.toBigDecimal(balance.get("frozen"), BigDecimal.ZERO));
                                interlaceWalletBalancesDO.setWalletType("CryptoAsset");
                                interlaceWalletBalancesDO.setCreateTime(System.currentTimeMillis());
                                interlaceWalletBalancesDO.setUpdateTime(System.currentTimeMillis());
                                interlaceWalletBalancesDO.setVirtualAvailable(BigDecimal.ZERO);
                                interlaceWalletBalancesDO.setVirtualPending(BigDecimal.ZERO);
                                interlaceWalletBalancesDO.setVirtualFrozen(BigDecimal.ZERO);
                                interlaceBalancesMapper.insert(interlaceWalletBalancesDO);
                            }
                        }
                    }
                }
            }
        }
    }

    @Override
    public void assetsWithdrawal(Map data) {
        if (data != null) {
            InterlaceTransfersDO transfersDO = interlaceTransfersMapper.selectOne(new LambdaQueryWrapper<InterlaceTransfersDO>()
                .eq(InterlaceTransfersDO::getRid, Convert.toStr(data.get("id"))));
            if (transfersDO != null) {
                transfersDO.setStatus(Convert.toStr(data.get("status")));
                transfersDO.setRiskLevel(Convert.toStr(data.get("riskLevel")));
                transfersDO.setTransactionHash(Convert.toStr(data.get("transactionHash")));
                transfersDO.setUpdateTime(System.currentTimeMillis());
                interlaceTransfersMapper.updateById(transfersDO);
                /** 推送-交易成功 */
                if ("Closed".equals(Convert.toStr(data.get("status")))) {
                    String pushType = "withdrawal_success";
                    PushNotificationEnum notification = PushNotificationEnum.fromPushType(pushType);
                    String zhContent = notification.getZhContent();
                    zhContent = MessageFormat.format(zhContent, transfersDO.getSourceAmount(), transfersDO.getSourceCurrency());
                    String enContent = notification.getEnContent();
                    enContent = MessageFormat.format(enContent, transfersDO.getSourceAmount(), transfersDO.getSourceCurrency());
                    String jaContent = notification.getJaContent();
                    jaContent = MessageFormat.format(jaContent, transfersDO.getSourceAmount(), transfersDO.getSourceCurrency());
                    pushService.push(pushType, zhContent, enContent, jaContent, transfersDO.getUid());
                }
                /** 推送-交易失败 */
                if ("Fail".equals(Convert.toStr(data.get("status")))) {
                    String pushType = "transaction_failed";
                    PushNotificationEnum notification = PushNotificationEnum.fromPushType(pushType);
                    String zhContent = notification.getZhContent();
                    String enContent = notification.getEnContent();
                    String jaContent = notification.getJaContent();
                    pushService.push(pushType, zhContent, enContent, jaContent, transfersDO.getUid());
                }
            }
        }
    }

    @Async
    @Override
    public void assetsDeposit(Map data) {
        if (data != null) {
            String accountId = Convert.toStr(data.get("accountId"));
            String status = Convert.toStr(data.get("status"));
            InterlaceMemberDO interlaceMemberDO = interlaceMemberMapper.selectOne(new LambdaQueryWrapper<InterlaceMemberDO>()
                .eq(InterlaceMemberDO::getInterlaceAccountId, accountId));
            InterlaceTransfersDO interlaceTransfersDO = new InterlaceTransfersDO();
            interlaceTransfersDO.setScene("assets_deposit");
            if (interlaceMemberDO != null) {
                interlaceTransfersDO.setUid(interlaceMemberDO.getId());
            }
            interlaceTransfersDO.setRid(Convert.toStr(data.get("id")));
            interlaceTransfersDO.setAccountId(accountId);
            interlaceTransfersDO.setSourceType("crypto_assets");
            interlaceTransfersDO.setSourceChain(Convert.toStr(data.get("chain")));
            interlaceTransfersDO.setSourceAddress(Convert.toStr(data.get("from")));
            interlaceTransfersDO.setSourceCurrency(Convert.toStr(data.get("currency")));
            interlaceTransfersDO.setSourceAmount(Convert.toBigDecimal(data.get("amount")));
            interlaceTransfersDO.setDestinationChain(Convert.toStr(data.get("chain")));
            interlaceTransfersDO.setDestinationAddress(Convert.toStr(data.get("to")));
            interlaceTransfersDO.setDestinationCurrency(Convert.toStr(data.get("currency")));
            interlaceTransfersDO.setDestinationAmount(Convert.toBigDecimal(data.get("amount")));
            interlaceTransfersDO.setStatus("PendingEffect");
            interlaceTransfersDO.setRiskLevel(Convert.toStr(data.get("riskLevel")));
            interlaceTransfersDO.setTransactionHash(Convert.toStr(data.get("transactionHash")));
            interlaceTransfersDO.setCreateTime(System.currentTimeMillis());
            interlaceTransfersDO.setUpdateTime(System.currentTimeMillis());

            /** 发起子加密账户向主账户转移 */
            if ("Closed".equals(status)) {
                HandleInternalTransferCryptoBO transferCrypto = new HandleInternalTransferCryptoBO();
                transferCrypto.setSourceAccountId(accountId);
                transferCrypto.setAmount(Convert.toBigDecimal(data.get("amount")));
                transferCrypto.setCurrency(Convert.toStr(data.get("currency")));
                InterlaceInternalTransferDO internalTransferDO = interlaceCryptoService.cryptoAssetsToMasterWallet(transferCrypto);
                if (internalTransferDO != null) {
                    interlaceTransfersDO.setStatus("Closed");
                    interlaceTransfersDO.setTransferId(internalTransferDO.getRid());
                    /** 更新子主加密钱包 */
                    interlaceCommunalService.updateCryptoWallet(accountId, Convert.toStr(data.get("currency")), Convert.toBigDecimal(data.get("amount")), "increase");
                }
            }
            interlaceTransfersDO.setSn(SnCreator.generateCTSn());
            interlaceTransfersMapper.insert(interlaceTransfersDO);

            /** 推送-到账通知 */
            String pushType = "incoming_transaction";
            PushNotificationEnum notification = PushNotificationEnum.fromPushType(pushType);
            String zhContent = notification.getZhContent();
            zhContent = MessageFormat.format(zhContent, Convert.toBigDecimal(data.get("amount")), Convert.toStr(data.get("currency")));
            String enContent = notification.getEnContent();
            enContent = MessageFormat.format(enContent, Convert.toBigDecimal(data.get("amount")), Convert.toStr(data.get("currency")));
            String jaContent = notification.getJaContent();
            jaContent = MessageFormat.format(jaContent, Convert.toBigDecimal(data.get("amount")), Convert.toStr(data.get("currency")));
            pushService.push(pushType, zhContent, enContent, jaContent, interlaceTransfersDO.getUid());

        }
    }

    @Override
    public void cardHolder(Map data) {
        if (data != null) {
            InterlaceCardHolderDO cardHolderDO = interlaceCardHolderMapper.selectOne(new LambdaQueryWrapper<InterlaceCardHolderDO>()
                .eq(InterlaceCardHolderDO::getRid, Convert.toStr(data.get("id"))));
            if (cardHolderDO != null) {
                cardHolderDO.setFirstName(Convert.toStr(data.get("firstName")));
                cardHolderDO.setLastName(Convert.toStr(data.get("lastName")));
                cardHolderDO.setEmail(Convert.toStr(data.get("email")));
                cardHolderDO.setUserName(Convert.toStr(data.get("userName")));
                cardHolderDO.setStatus(Convert.toStr(data.get("status")));
                cardHolderDO.setUpdateTime(System.currentTimeMillis());
                interlaceCardHolderMapper.updateById(cardHolderDO);
            }
        }
    }

    @Async
    @Override
    public void budgetTransaction(Map data) {
        if (data != null) {
            String accountId = Convert.toStr(data.get("accountId"));
            String status = Convert.toStr(data.get("status"));
            String type = Convert.toStr(data.get("type"));
            Long uid = null;
            InterlaceMemberDO memberDO = interlaceMemberMapper.selectOne(new LambdaQueryWrapper<InterlaceMemberDO>()
                .eq(InterlaceMemberDO::getInterlaceAccountId, accountId));
            String clientTransactionId = Convert.toStr(data.get("clientTransactionId"));

            InterlaceBudgetTransactionDO budgetTransactionDO = new InterlaceBudgetTransactionDO();
            if (memberDO != null) {
                budgetTransactionDO.setUid(memberDO.getId());
                uid = memberDO.getId();
            }
            budgetTransactionDO.setRid(Convert.toStr(data.get("id")));
            budgetTransactionDO.setAccountId(accountId);
            budgetTransactionDO.setBudgetId(Convert.toStr(data.get("budgetId")));
            budgetTransactionDO.setCardId(Convert.toStr(data.get("cardId")));
            budgetTransactionDO.setAmount(Convert.toBigDecimal(data.get("amount")));
            budgetTransactionDO.setFee(Convert.toBigDecimal(data.get("fee")));
            budgetTransactionDO.setType(type);
            budgetTransactionDO.setClientTransactionId(clientTransactionId);
            budgetTransactionDO.setStatus(status);
            budgetTransactionDO.setTransactionTime(System.currentTimeMillis());
            budgetTransactionDO.setCreateTime(System.currentTimeMillis());
            budgetTransactionDO.setUpdateTime(System.currentTimeMillis());
            interlaceBudgetTransactionMapper.insert(budgetTransactionDO);

            /** 更新balance */
            ListAllBalancesRequest balancesRequest = new ListAllBalancesRequest();
            balancesRequest.setAccountId(accountId);
            balancesRequest.setLimit("10");
            balancesRequest.setPage("0");
            balancesRequest.setWalletType("Budget");
            interlaceCommunalService.updateBalances(balancesRequest);

            /** 开卡费 */
            if ("CreateCardFee".equals(type) && "Closed".equals(status)) {
            /** 保存量子账户开卡 */
            InterlaceQuantumTransferDO quantumTransferDO = new InterlaceQuantumTransferDO();
            quantumTransferDO.setUid(uid);
            quantumTransferDO.setAccountId(accountId);
            quantumTransferDO.setType("open_card_fee");
            quantumTransferDO.setAmount(Convert.toBigDecimal(data.get("fee")));
            quantumTransferDO.setTransferId(Convert.toStr(data.get("id")));
            quantumTransferDO.setStatus("Closed");
            quantumTransferDO.setCreateTime(System.currentTimeMillis());
            quantumTransferDO.setUpdateTime(System.currentTimeMillis());
            interlaceCommunalService.addQuantumTransfer(quantumTransferDO);

            /** 添加银行卡开卡交易 */
            String sn = SnCreator.generateQTSn();
            InterlaceCardTransactionDO cardTransactionDO = new InterlaceCardTransactionDO();
            cardTransactionDO.setUid(uid);
            cardTransactionDO.setSn(sn);
            cardTransactionDO.setAccountId(accountId);
            cardTransactionDO.setCardId(Convert.toStr(data.get("cardId")));
            cardTransactionDO.setCurrency("USD");
            cardTransactionDO.setAmount(Convert.toBigDecimal(data.get("fee")));
            cardTransactionDO.setType("Open_Card_Fee");
            cardTransactionDO.setStatus("Closed");
            cardTransactionDO.setTransactionTime(System.currentTimeMillis());
            cardTransactionDO.setTransactionCurrency("USD");
            cardTransactionDO.setTransactionAmount(Convert.toBigDecimal(data.get("fee")));
            cardTransactionDO.setMerchantName("Card Activation Fee");
            cardTransactionDO.setCreateTime(System.currentTimeMillis());
            cardTransactionDO.setUpdateTime(System.currentTimeMillis());
            cardTransactionDO.setFee(BigDecimal.ZERO);
            interlaceCardTransactionMapper.insert(cardTransactionDO);

            BigDecimal amount = Convert.toBigDecimal(data.get("amount")).add(Convert.toBigDecimal(data.get("fee")));
            /** 统计账单 */
            interlaceCardBillStatisticsService.decreaseAmount(Convert.toStr(data.get("cardId")), amount);
            }

            if ("TransferOut".equals(type) && "Closed".equals(status)) {
                /** 处理用户fiat -> crypto记录 */
                InterlaceTransfersDO interlaceTransfersDO = interlaceTransfersMapper.selectOne(new LambdaQueryWrapper<InterlaceTransfersDO>()
                    .eq(InterlaceTransfersDO::getTransferId, clientTransactionId)
                    .eq(InterlaceTransfersDO::getScene, "buy")
                    .eq(InterlaceTransfersDO::getStatus, "Pending"));
                if (interlaceTransfersDO != null) {
                    /** 子量子账户->主量子账户 */
                    InterlaceInternalTransferDO internalTransferDO = interlaceCryptoService.subAccountToMasterAccount(accountId, budgetTransactionDO.getAmount());
                    if (internalTransferDO != null) {
                        interlaceTransfersDO.setStatus(internalTransferDO.getStatus());
                        interlaceTransfersDO.setRid(internalTransferDO.getRid());
                        interlaceTransfersDO.setUpdateTime(System.currentTimeMillis());
                        interlaceTransfersMapper.updateById(interlaceTransfersDO);

                        /** 更新子主加密钱包 */
                        interlaceCommunalService.updateCryptoWallet(accountId, interlaceTransfersDO.getDestinationCurrency(), interlaceTransfersDO.getDestinationAmount(), "increase");

                        /** 更新量子钱包记录 */
                        InterlaceQuantumTransferDO interlaceQuantumTransferDO = interlaceQuantumTransferMapper.selectOne(new LambdaQueryWrapper<InterlaceQuantumTransferDO>()
                            .eq(InterlaceQuantumTransferDO::getTransferId, clientTransactionId)
                            .eq(InterlaceQuantumTransferDO::getStatus, "Pending")
                            .eq(InterlaceQuantumTransferDO::getType, "quote_buy"));
                        if (interlaceQuantumTransferDO != null) {
                            interlaceQuantumTransferDO.setStatus(internalTransferDO.getStatus());
                            interlaceQuantumTransferDO.setClientTransactionId(internalTransferDO.getRid());
                            interlaceQuantumTransferDO.setUpdateTime(System.currentTimeMillis());
                            interlaceQuantumTransferMapper.updateById(interlaceQuantumTransferDO);
                        }

                        /** 将用户用fiat兑换的加密货币 */
                    }
                }

                /** 更新卡片管理费记录 */
                CardMgrFeeDO cardMgrFee = cardMgrFeeMapper.selectOne(new LambdaQueryWrapper<CardMgrFeeDO>()
                    .eq(CardMgrFeeDO::getTransferId, clientTransactionId)
                    .eq(CardMgrFeeDO::getStatus, "2")
                    .last("limit 1"));
                if (cardMgrFee != null) {
                    /** 子加密账户->主加密账户 */
                    InterlaceInternalTransferDO internalTransferDO = interlaceCryptoService.subAccountToMasterAccount(accountId, budgetTransactionDO.getAmount());
                    if (internalTransferDO != null) {
                        cardMgrFee.setStatus("1");
                        cardMgrFee.setUpdateAt(System.currentTimeMillis());
                        cardMgrFeeMapper.updateById(cardMgrFee);
                        /** 更新量子钱包记录 */
                        InterlaceQuantumTransferDO interlaceQuantumTransferDO = interlaceQuantumTransferMapper.selectOne(new LambdaQueryWrapper<InterlaceQuantumTransferDO>()
                            .eq(InterlaceQuantumTransferDO::getTransferId, clientTransactionId)
                            .eq(InterlaceQuantumTransferDO::getStatus, "Pending")
                            .eq(InterlaceQuantumTransferDO::getType, "card_mgt"));
                        if (interlaceQuantumTransferDO != null) {
                            interlaceQuantumTransferDO.setStatus("Closed");
                            interlaceQuantumTransferDO.setUpdateTime(System.currentTimeMillis());
                            interlaceQuantumTransferMapper.updateById(interlaceQuantumTransferDO);
                        }
                    }
                }
            }

            if ("TransferIn".equals(type)) {
                /** 更新加密货币交易记录 */
                InterlaceTransfersDO interlaceTransfersDO = interlaceTransfersMapper.selectOne(new LambdaQueryWrapper<InterlaceTransfersDO>()
                    .eq(InterlaceTransfersDO::getTransferId, clientTransactionId)
                    .eq(InterlaceTransfersDO::getStatus, "Pending"));
                if (interlaceTransfersDO != null) {
                    if ("Closed".equals(status)) {
                        interlaceTransfersDO.setStatus(status);
                        interlaceTransfersDO.setUpdateTime(System.currentTimeMillis());
                        interlaceTransfersMapper.updateById(interlaceTransfersDO);
                    }
                }
                /** 更新量子钱包记录 */
                InterlaceQuantumTransferDO interlaceQuantumTransferDO = interlaceQuantumTransferMapper.selectOne(new LambdaQueryWrapper<InterlaceQuantumTransferDO>()
                    .eq(InterlaceQuantumTransferDO::getTransferId, clientTransactionId)
                    .eq(InterlaceQuantumTransferDO::getStatus, "Pending")
                    .eq(InterlaceQuantumTransferDO::getType, "quote_sell"));
                if (interlaceQuantumTransferDO != null) {
                    interlaceQuantumTransferDO.setStatus(status);
                    interlaceQuantumTransferDO.setUpdateTime(System.currentTimeMillis());
                    interlaceQuantumTransferMapper.updateById(interlaceQuantumTransferDO);
                }
            }

            /** 消费失败 */
            if ("Consumption".equals(type) && "Fail".equals(status)) {
                /** 推送-交易失败 */
                String pushType = "transaction_failed";
                PushNotificationEnum notification = PushNotificationEnum.fromPushType(pushType);
                String zhContent = notification.getZhContent();
                String enContent = notification.getEnContent();
                String jaContent = notification.getJaContent();
                pushService.push(pushType, zhContent, enContent, jaContent, uid);
            }
            /** 退款 */
            if ("Refund".equals(type) && "Closed".equals(status)) {
                /** 推送-到账通知 */
                String pushType = "incoming_transaction";
                PushNotificationEnum notification = PushNotificationEnum.fromPushType(pushType);
                String zhContent = notification.getZhContent();
                zhContent = MessageFormat.format(zhContent, Convert.toBigDecimal(data.get("amount")), "USD");
                String enContent = notification.getEnContent();
                enContent = MessageFormat.format(enContent, Convert.toBigDecimal(data.get("amount")), "USD");
                String jaContent = notification.getJaContent();
                jaContent = MessageFormat.format(jaContent, Convert.toBigDecimal(data.get("amount")), "USD");
                pushService.push(pushType, zhContent, enContent, jaContent, uid);
            }
            /** 交易冲正 */
            if ("Reversal".equals(type) && "Closed".equals(status)) {
                /** 推送-到账通知 */
                String pushType = "incoming_transaction";
                PushNotificationEnum notification = PushNotificationEnum.fromPushType(pushType);
                String zhContent = notification.getZhContent();
                zhContent = MessageFormat.format(zhContent, Convert.toBigDecimal(data.get("amount")), "USD");
                String enContent = notification.getEnContent();
                enContent = MessageFormat.format(enContent, Convert.toBigDecimal(data.get("amount")), "USD");
                String jaContent = notification.getJaContent();
                jaContent = MessageFormat.format(jaContent, Convert.toBigDecimal(data.get("amount")), "USD");
                pushService.push(pushType, zhContent, enContent, jaContent, uid);
            }
        }
    }

    @Async
    @Override
    public void createCard(Map data) {
        if (data != null) {
            String accountId = Convert.toStr(data.get("accountId"));
            String cardId = Convert.toStr(data.get("id"));
            String labelId = Convert.toStr(data.get("label"));
            InterlaceInfinityCardDO infinityCardDO = interlaceInfinityCardMapper.selectOne(new LambdaQueryWrapper<InterlaceInfinityCardDO>()
                .eq(InterlaceInfinityCardDO::getCardId, cardId).last("limit 1"));
            if (infinityCardDO == null) {
                infinityCardDO = new InterlaceInfinityCardDO();
                InterlaceCardApplyDO cardApplyDO = interlaceCardApplyMapper.selectOne(new LambdaQueryWrapper<InterlaceCardApplyDO>()
                    .eq(InterlaceCardApplyDO::getLabelId, labelId));
                if (cardApplyDO != null) {
                    cardApplyDO.setStatus("Closed");
                    cardApplyDO.setUpdateTime(System.currentTimeMillis());
                    InterlaceMemberDO memberDO = interlaceMemberMapper.selectOne(new LambdaQueryWrapper<InterlaceMemberDO>()
                        .eq(InterlaceMemberDO::getInterlaceAccountId, accountId));
                    if (memberDO != null) {
                        infinityCardDO.setUid(memberDO.getId());
                    }
                    infinityCardDO.setCardId(cardId);
                    infinityCardDO.setAccount(accountId);
                    infinityCardDO.setToken(Convert.toStr(data.get("token")));
                    infinityCardDO.setStatus(Convert.toStr(data.get("status")));
                    infinityCardDO.setCurrency(Convert.toStr(data.get("currency")));
                    infinityCardDO.setCardMode(cardApplyDO.getCardMode());
                    infinityCardDO.setBin(cardApplyDO.getBin());
                    infinityCardDO.setNetwork(cardApplyDO.getNetwork());
                    String userName = Convert.toStr(data.get("userName"));
                    String[] userNames = userName.split(" ");
                    if (userNames.length == 2) {
                        infinityCardDO.setFirstName(userNames[0]);
                        infinityCardDO.setLastName(userNames[1]);
                    }
                    infinityCardDO.setCardNoLastFour(Convert.toStr(data.get("cardNoLastFour")));
                    infinityCardDO.setLabel(Convert.toStr(data.get("label")));
                    infinityCardDO.setUseType(Convert.toStr(data.get("useType")));
                    infinityCardDO.setBalanceId(Convert.toStr(data.get("balanceId")));
                    infinityCardDO.setBudgetId(Convert.toStr(data.get("budgetId")));
                    Map cardAddress = (Map) data.get("cardAddress");
                    if (cardAddress != null) {
                        infinityCardDO.setBillingAddressLine1(Convert.toStr(cardAddress.get("addressLine1")));
                        infinityCardDO.setBillingAddressLine2(Convert.toStr(cardAddress.get("addressLine2")));
                        infinityCardDO.setBillingAddressCity(Convert.toStr(cardAddress.get("city")));
                        infinityCardDO.setBillingAddressState(Convert.toStr(cardAddress.get("state")));
                        infinityCardDO.setBillingAddressCountry(Convert.toStr(cardAddress.get("country")));
                        infinityCardDO.setBillingAddressPostalCode(Convert.toStr(cardAddress.get("postalCode")));
                    }
                    try {
                        Map detailsResponse = interlaceService.infinityCardDetails(infinityCardDO.getCardId());
                        if (detailsResponse != null) {
                            infinityCardDO.setCardNo(Convert.toStr(detailsResponse.get("cardNo")));
                        }
                    } catch (Exception e) {
                        log.error("获取卡详询信息失败", e);
                    }
                    infinityCardDO.setCreateTime(System.currentTimeMillis());
                    infinityCardDO.setUpdateTime(System.currentTimeMillis());
                    interlaceInfinityCardMapper.insert(infinityCardDO);
                    cardApplyDO.setCardId(infinityCardDO.getId());
                    interlaceCardApplyMapper.updateById(cardApplyDO);

                    /** 添加卡片管理费待收取记录 */
                    BigDecimal cardMgtFee = Convert.toBigDecimal(5.00);
                    FeeThaliVO feeThaliVO = feeThaliMapper.selectVoOne(new LambdaQueryWrapper<FeeThaliDO>()
                        .eq(FeeThaliDO::getType, "card_mgt")
                        .eq(FeeThaliDO::getStatus, "0")
                        .last("limit 1"));
                    if (feeThaliVO != null) {
                        cardMgtFee = Convert.toBigDecimal(feeThaliVO.getFeeConfig());
                    }
                    String createMonth = DateUtil.timestampToDateStr();
                    CardMgrFeeDO mgrFeeDO = new CardMgrFeeDO();
                    mgrFeeDO.setUid(infinityCardDO.getUid());
                    mgrFeeDO.setCardId(infinityCardDO.getCardId());
                    mgrFeeDO.setCardNo(infinityCardDO.getCardNo());
                    mgrFeeDO.setCollectMonth(createMonth);
                    mgrFeeDO.setCreateAt(System.currentTimeMillis());
                    mgrFeeDO.setUpdateAt(System.currentTimeMillis());
                    mgrFeeDO.setCollectAmount(cardMgtFee);
                    mgrFeeDO.setStartTime(DateUtil.timestampToDateStrToyyyyMMdd());
                    mgrFeeDO.setDeadlineTime(CardMgtFeeUtil.calculateNextChargeDate(DateUtil.timestampToDateStrToyyyyMMdd()));
                    mgrFeeDO.setStatus("0");
                    cardMgrFeeMapper.insert(mgrFeeDO);
                }
            }
        }
    }

    @Override
    public void cardTransaction(Map data) {
        if (data != null) {
            String rid = Convert.toStr(data.get("id"));
            String type = Convert.toStr(data.get("type"));
            String cardTransactionId = Convert.toStr(data.get("cardTransactionId"));
            String relatedCardTransactionId = Convert.toStr(data.get("relatedCardTransactionId"));
            String accountId = Convert.toStr(data.get("accountId"));
            String cardId = Convert.toStr(data.get("cardId"));
            InterlaceMemberDO memberDO = interlaceMemberMapper.selectOne(new LambdaQueryWrapper<InterlaceMemberDO>()
                .eq(InterlaceMemberDO::getInterlaceAccountId, accountId));
            Long uid = null;
            if (memberDO != null) {
                uid = memberDO.getId();
            }
            InterlaceInfinityCardDO infinityCardDO = interlaceInfinityCardMapper.selectOne(new LambdaQueryWrapper<InterlaceInfinityCardDO>()
                .eq(InterlaceInfinityCardDO::getCardId, cardId));
            BigDecimal amount = BigDecimal.ZERO;
            if ("Consumption".equals(type)) {
                InterlaceCardTransactionDO cardTransactionDO = interlaceCardTransactionMapper.selectOne(new LambdaQueryWrapper<InterlaceCardTransactionDO>()
                    .eq(InterlaceCardTransactionDO::getCardTransactionId, cardTransactionId));
                if (cardTransactionDO == null) {
                    String sn = SnCreator.generateQTSn();
                    cardTransactionDO = new InterlaceCardTransactionDO();
                    cardTransactionDO.setUid(uid);
                    cardTransactionDO.setSn(sn);
                    cardTransactionDO.setAccountId(accountId);
                    cardTransactionDO.setRid(rid);
                    cardTransactionDO.setCardId(cardId);
                    cardTransactionDO.setCurrency(Convert.toStr(data.get("currency")));
                    cardTransactionDO.setAmount(Convert.toBigDecimal(data.get("amount")));
                    cardTransactionDO.setType(type);
                    cardTransactionDO.setClientTransactionId(Convert.toStr(data.get("clientTransactionId")));
                    cardTransactionDO.setCardTransactionId(cardTransactionId);
                    cardTransactionDO.setRelatedCardTransactionId(relatedCardTransactionId);
                    cardTransactionDO.setRemark(Convert.toStr(data.get("remark")));
                    cardTransactionDO.setDetail(Convert.toStr(data.get("detail")));
                    cardTransactionDO.setStatus(Convert.toStr(data.get("status")));
                    cardTransactionDO.setTransactionTime(System.currentTimeMillis());
                    cardTransactionDO.setTransactionCurrency(Convert.toStr(data.get("transactionCurrency")));
                    cardTransactionDO.setTransactionAmount(Convert.toBigDecimal(data.get("transactionAmount")));
                    cardTransactionDO.setMerchantName(Convert.toStr(data.get("merchantName")));
                    cardTransactionDO.setMcc(Convert.toStr(data.get("mcc")));
                    cardTransactionDO.setMccCategory(Convert.toStr(data.get("mccCategory")));
                    cardTransactionDO.setMerchantCity(Convert.toStr(data.get("merchantCity")));
                    cardTransactionDO.setMerchantCountry(Convert.toStr(data.get("merchantCountry")));
                    cardTransactionDO.setMerchantState(Convert.toStr(data.get("merchantState")));
                    cardTransactionDO.setMerchantZipcode(Convert.toStr(data.get("merchantZipcode")));
                    cardTransactionDO.setMerchantMid(Convert.toStr(data.get("merchantMid")));
                    cardTransactionDO.setCreateTime(System.currentTimeMillis());
                    cardTransactionDO.setUpdateTime(System.currentTimeMillis());
                    cardTransactionDO.setFee(Convert.toBigDecimal(data.get("fee")));
                    interlaceCardTransactionMapper.insert(cardTransactionDO);

                    /** 保存手续费 */
                    InterlaceCardTransactionFeeDO cardTransactionFeeDO = new InterlaceCardTransactionFeeDO();
                    cardTransactionFeeDO.setTid(cardTransactionDO.getId());
                    cardTransactionFeeDO.setCurrency(Convert.toStr(data.get("currency")));
                    cardTransactionFeeDO.setAmount(Convert.toBigDecimal(data.get("fee")));
                    cardTransactionFeeDO.setType(type);
                    cardTransactionFeeDO.setCreateTime(System.currentTimeMillis());
                    interlaceCardTransactionFeeMapper.insert(cardTransactionFeeDO);

                    /** 新增量子交易记录 */
                    InterlaceQuantumTransferDO interlaceQuantumTransferDO = new InterlaceQuantumTransferDO();
                    interlaceQuantumTransferDO.setUid(uid);
                    interlaceQuantumTransferDO.setAccountId(accountId);
                    interlaceQuantumTransferDO.setType(Convert.toStr(data.get("type")));
                    interlaceQuantumTransferDO.setAmount(Convert.toBigDecimal(data.get("amount")));
                    interlaceQuantumTransferDO.setTransferObj(JSONUtil.toJsonStr(cardTransactionDO));
                    interlaceQuantumTransferDO.setClientTransactionId(cardTransactionId);
                    interlaceQuantumTransferDO.setCreateTime(System.currentTimeMillis());
                    interlaceQuantumTransferDO.setUpdateTime(System.currentTimeMillis());
                    if (infinityCardDO != null) {
                        interlaceQuantumTransferDO.setAdditional1(infinityCardDO.getCardId());
                        interlaceQuantumTransferDO.setAdditional2(infinityCardDO.getCardNoLastFour());
                    }
                    interlaceQuantumTransferDO.setSn(sn);
                    interlaceQuantumTransferDO.setStatus(Convert.toStr(data.get("status")));
                    interlaceQuantumTransferMapper.insert(interlaceQuantumTransferDO);

                    /** 保存手续费 */
                    InterlaceQuantumTransferFeesDO interlaceQuantumTransferFees = new InterlaceQuantumTransferFeesDO();
                    interlaceQuantumTransferFees.setQid(interlaceQuantumTransferDO.getId());
                    interlaceQuantumTransferFees.setCurrency(Convert.toStr(data.get("currency")));
                    interlaceQuantumTransferFees.setAmount(Convert.toBigDecimal(data.get("fee")));
                    interlaceQuantumTransferFees.setCreateTime(System.currentTimeMillis());
                    interlaceQuantumTransferFees.setType("Consumption");
                    interlaceQuantumTransferFeesMapper.insert(interlaceQuantumTransferFees);

                    /** 推送-交易成功 */
                    if ("Closed".equals(Convert.toStr(data.get("status"))) || "Pending".equals(Convert.toStr(data.get("status")))) {
                        String pushType = "transaction_success";
                        PushNotificationEnum notification = PushNotificationEnum.fromPushType(pushType);
                        String zhContent = notification.getZhContent();
                        zhContent = MessageFormat.format(zhContent, cardTransactionDO.getTransactionAmount(), cardTransactionDO.getTransactionCurrency(), cardTransactionDO.getMerchantName());
                        String enContent = notification.getEnContent();
                        enContent = MessageFormat.format(enContent, cardTransactionDO.getTransactionAmount(), cardTransactionDO.getTransactionCurrency(), cardTransactionDO.getMerchantName());
                        String jaContent = notification.getJaContent();
                        jaContent = MessageFormat.format(jaContent, cardTransactionDO.getTransactionAmount(), cardTransactionDO.getTransactionCurrency(), cardTransactionDO.getMerchantName());
                        pushService.push(pushType, zhContent, enContent, jaContent, cardTransactionDO.getUid());
                    }
                    amount = Convert.toBigDecimal(data.get("amount")).add(Convert.toBigDecimal(data.get("fee")));
                    /** 统计账单 */
                    interlaceCardBillStatisticsService.decreaseAmount(cardId, amount);
                } else {
                    /** 更新卡交易记录 */
                    cardTransactionDO.setStatus(Convert.toStr(data.get("status")));
                    cardTransactionDO.setRemark(Convert.toStr(data.get("remark")));
                    interlaceCardTransactionMapper.updateById(cardTransactionDO);
                    /** 更新量子交易记录 */
                    InterlaceQuantumTransferDO interlaceQuantumTransferDO = interlaceQuantumTransferMapper.selectOne(new LambdaQueryWrapper<InterlaceQuantumTransferDO>()
                        .eq(InterlaceQuantumTransferDO::getClientTransactionId, cardTransactionId)
                        .eq(InterlaceQuantumTransferDO::getType, "Consumption"));
                    if (interlaceQuantumTransferDO != null) {
                        interlaceQuantumTransferDO.setStatus(Convert.toStr(data.get("status")));
                        interlaceQuantumTransferDO.setTransferObj(JSONUtil.toJsonStr(cardTransactionDO));
                        interlaceQuantumTransferDO.setUpdateTime(System.currentTimeMillis());
                        interlaceQuantumTransferMapper.updateById(interlaceQuantumTransferDO);
                    }
                }
            } else {
                String sn = SnCreator.generateQTSn();
                InterlaceCardTransactionDO cardTransactionDO = new InterlaceCardTransactionDO();
                cardTransactionDO.setUid(uid);
                cardTransactionDO.setSn(sn);
                cardTransactionDO.setAccountId(accountId);
                cardTransactionDO.setRid(rid);
                cardTransactionDO.setCardId(cardId);
                cardTransactionDO.setCurrency(Convert.toStr(data.get("currency")));
                cardTransactionDO.setAmount(Convert.toBigDecimal(data.get("amount")));
                cardTransactionDO.setType(type);
                cardTransactionDO.setClientTransactionId(Convert.toStr(data.get("clientTransactionId")));
                cardTransactionDO.setCardTransactionId(cardTransactionId);
                cardTransactionDO.setRelatedCardTransactionId(relatedCardTransactionId);
                cardTransactionDO.setRemark(Convert.toStr(data.get("remark")));
                cardTransactionDO.setDetail(Convert.toStr(data.get("detail")));
                cardTransactionDO.setStatus(Convert.toStr(data.get("status")));
                cardTransactionDO.setTransactionTime(System.currentTimeMillis());
                cardTransactionDO.setTransactionCurrency(Convert.toStr(data.get("transactionCurrency")));
                cardTransactionDO.setTransactionAmount(Convert.toBigDecimal(data.get("transactionAmount")));
                cardTransactionDO.setMerchantName(Convert.toStr(data.get("merchantName")));
                cardTransactionDO.setMcc(Convert.toStr(data.get("mcc")));
                cardTransactionDO.setMccCategory(Convert.toStr(data.get("mccCategory")));
                cardTransactionDO.setMerchantCity(Convert.toStr(data.get("merchantCity")));
                cardTransactionDO.setMerchantCountry(Convert.toStr(data.get("merchantCountry")));
                cardTransactionDO.setMerchantState(Convert.toStr(data.get("merchantState")));
                cardTransactionDO.setMerchantZipcode(Convert.toStr(data.get("merchantZipcode")));
                cardTransactionDO.setMerchantMid(Convert.toStr(data.get("merchantMid")));
                cardTransactionDO.setCreateTime(System.currentTimeMillis());
                cardTransactionDO.setUpdateTime(System.currentTimeMillis());
                cardTransactionDO.setFee(Convert.toBigDecimal(data.get("fee")));
                interlaceCardTransactionMapper.insert(cardTransactionDO);

                InterlaceCardTransactionFeeDO cardTransactionFeeDO = new InterlaceCardTransactionFeeDO();
                cardTransactionFeeDO.setTid(cardTransactionDO.getId());
                cardTransactionFeeDO.setCurrency(Convert.toStr(data.get("currency")));
                cardTransactionFeeDO.setAmount(Convert.toBigDecimal(data.get("fee")));
                cardTransactionFeeDO.setType(type);
                cardTransactionFeeDO.setCreateTime(System.currentTimeMillis());
                interlaceCardTransactionFeeMapper.insert(cardTransactionFeeDO);

                /** 新增量子交易记录 */
                InterlaceQuantumTransferDO interlaceQuantumTransferDO = new InterlaceQuantumTransferDO();
                interlaceQuantumTransferDO.setUid(uid);
                interlaceQuantumTransferDO.setAccountId(accountId);
                interlaceQuantumTransferDO.setType(Convert.toStr(data.get("type")));
                interlaceQuantumTransferDO.setAmount(Convert.toBigDecimal(data.get("amount")));
                interlaceQuantumTransferDO.setTransferObj(JSONUtil.toJsonStr(cardTransactionDO));
                interlaceQuantumTransferDO.setClientTransactionId(cardTransactionId);
                interlaceQuantumTransferDO.setCreateTime(System.currentTimeMillis());
                interlaceQuantumTransferDO.setUpdateTime(System.currentTimeMillis());
                if (infinityCardDO != null) {
                    interlaceQuantumTransferDO.setAdditional1(infinityCardDO.getCardId());
                    interlaceQuantumTransferDO.setAdditional2(infinityCardDO.getCardNoLastFour());
                }
                interlaceQuantumTransferDO.setSn(sn);
                interlaceQuantumTransferDO.setStatus(Convert.toStr(data.get("status")));
                interlaceQuantumTransferMapper.insert(interlaceQuantumTransferDO);

                /** 保存对应手续费 */
                InterlaceQuantumTransferFeesDO interlaceQuantumTransferFees = new InterlaceQuantumTransferFeesDO();
                interlaceQuantumTransferFees.setQid(interlaceQuantumTransferDO.getId());
                interlaceQuantumTransferFees.setCurrency(Convert.toStr(data.get("currency")));
                interlaceQuantumTransferFees.setAmount(Convert.toBigDecimal(data.get("fee")));
                interlaceQuantumTransferFees.setCreateTime(System.currentTimeMillis());
                interlaceQuantumTransferFees.setType("Consumption");
                interlaceQuantumTransferFeesMapper.insert(interlaceQuantumTransferFees);

                if ("Reversal".equals(type) || "TransferIn".equals(type) || "Credit".equals(type)) {
                    amount = Convert.toBigDecimal(data.get("amount")).subtract(Convert.toBigDecimal(data.get("fee")));
                    /** 统计账单 */
                    interlaceCardBillStatisticsService.increaseAmount(cardId, amount);
                } else {
                    amount = Convert.toBigDecimal(data.get("amount")).add(Convert.toBigDecimal(data.get("fee")));
                    /** 统计账单 */
                    interlaceCardBillStatisticsService.decreaseAmount(cardId, amount);
                }
            }
        }
    }

    @Override
    public void cardStateChange(Map data) {
        if (data != null) {
            String cardId = Convert.toStr(data.get("id"));
            String accountId = Convert.toStr(data.get("accountId"));
            String cardStatus = Convert.toStr(data.get("status"));
            InterlaceInfinityCardDO infinityCardDO = interlaceInfinityCardMapper.selectOne(new LambdaQueryWrapper<InterlaceInfinityCardDO>()
                .eq(InterlaceInfinityCardDO::getCardId, cardId)
                .eq(InterlaceInfinityCardDO::getAccount, accountId)
                .last("limit 1"));
            if (infinityCardDO != null) {
                infinityCardDO.setStatus(cardStatus);
                infinityCardDO.setUpdateTime(System.currentTimeMillis());
                interlaceInfinityCardMapper.updateById(infinityCardDO);

                /** 推送-卡片激活提醒 */
                if ("Active".equals(cardStatus)) {
                    String pushType = "card_payment_service";
                    PushNotificationEnum notification = PushNotificationEnum.fromPushType(pushType);
                    String zhContent = notification.getZhContent();
                    String enContent = notification.getEnContent();
                    String jaContent = notification.getJaContent();
                    pushService.push(pushType, zhContent, enContent, jaContent, infinityCardDO.getUid());
                }
            }
        }
    }
}
